from PIL import Image
import os
import sys
import argparse
import glob


"""
使用方法
转换单个GIF文件：


python gif转png序列.py 示例.gif
转换目录中所有GIF文件：


python gif转png序列.py 图像目录/
使用通配符批量转换：


python gif转png序列.py *.gif
指定输出目录：


python gif转png序列.py *.gif -o 输出目录
强制单文件处理模式：
python gif转png序列.py 多个文件.gif -s
"""

def gif_to_png_sequence(gif_path, output_dir=None, prefix=None):
    """
    将单个GIF文件转换为PNG序列

    参数:
        gif_path (str): GIF文件路径
        output_dir (str): 输出目录，默认为GIF所在目录下的同名文件夹
        prefix (str): 输出文件名前缀，默认为GIF文件名
    """
    # 检查文件是否存在
    if not os.path.exists(gif_path):
        print(f"错误: 文件 '{gif_path}' 不存在")
        return False

    # 获取GIF文件名和目录
    gif_dir = os.path.dirname(gif_path) or "."
    gif_filename = os.path.basename(gif_path)
    gif_name = os.path.splitext(gif_filename)[0]

    # 设置默认输出目录和前缀
    if not output_dir:
        output_dir = os.path.join(gif_dir, f"{gif_name}_frames")
    if not prefix:
        prefix = gif_name

    # 创建输出目录
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    try:
        # 打开GIF文件
        with Image.open(gif_path) as img:
            frame_count = 0
            # 循环遍历所有帧
            while True:
                try:
                    # 保存当前帧为PNG
                    current_frame = img.convert('RGBA')
                    output_filename = f"{prefix}_{frame_count:03d}.png"
                    output_path = os.path.join(output_dir, output_filename)
                    current_frame.save(output_path)

                    # 获取下一帧
                    frame_count += 1
                    img.seek(frame_count)
                except EOFError:
                    # 到达GIF文件末尾
                    break

        print(f"转换完成: '{gif_path}' -> {frame_count} 帧图像保存到 '{output_dir}'")
        return True

    except Exception as e:
        print(f"转换过程中发生错误: {e}")
        return False


def batch_convert_gifs(gif_paths, output_base_dir=None):
    """
    批量转换多个GIF文件为PNG序列

    参数:
        gif_paths (list): GIF文件路径列表
        output_base_dir (str): 基础输出目录，如果指定，所有文件将输出到该目录下的子文件夹
    """
    success_count = 0
    fail_count = 0

    for gif_path in gif_paths:
        # 对每个GIF文件，如果指定了基础输出目录，则在其下创建子目录
        if output_base_dir:
            gif_name = os.path.splitext(os.path.basename(gif_path))[0]
            output_dir = os.path.join(output_base_dir, gif_name)
        else:
            output_dir = None

        result = gif_to_png_sequence(gif_path, output_dir)
        if result:
            success_count += 1
        else:
            fail_count += 1

    print(f"\n批量转换完成！成功: {success_count}, 失败: {fail_count}")


def get_all_gif_files(input_paths):
    """获取所有GIF文件路径列表"""
    gif_files = []

    for path in input_paths:
        # 如果是目录，获取目录中所有GIF文件
        if os.path.isdir(path):
            gif_files.extend(glob.glob(os.path.join(path, "*.gif")))
        # 如果是通配符路径，展开通配符
        elif "*" in path or "?" in path:
            gif_files.extend(glob.glob(path))
        # 如果是单个文件
        else:
            gif_files.append(path)

    # 过滤只保留GIF文件
    gif_files = [f for f in gif_files if f.lower().endswith('.gif')]
    return gif_files


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="将GIF图像批量转换为PNG图像序列")
    parser.add_argument("input_paths", nargs='+', help="GIF文件路径、目录或通配符")
    parser.add_argument("-o", "--output-dir", help="输出PNG序列的基础目录")
    parser.add_argument("-p", "--prefix", help="输出PNG文件名的前缀（仅在单文件模式下有效）")
    parser.add_argument("-s", "--single", action="store_true", help="以单个文件模式处理，即使提供了多个文件")

    args = parser.parse_args()

    # 获取所有GIF文件
    gif_files = get_all_gif_files(args.input_paths)

    if not gif_files:
        print("未找到任何GIF文件！")
        sys.exit(1)

    # 打印找到的文件数量
    print(f"找到 {len(gif_files)} 个GIF文件待转换")

    # 单文件模式或只有一个文件
    if args.single or len(gif_files) == 1:
        gif_to_png_sequence(gif_files[0], args.output_dir, args.prefix)
    # 批量模式
    else:
        batch_convert_gifs(gif_files, args.output_dir)